package it.koutifaris.travianmap.dal.sqlservices.dumpimporter;

import it.koutifaris.travianmap.dal.RevisionService.Revision;
import it.koutifaris.travianmap.dal.sqlservices.Auditable;
import it.koutifaris.travianmap.dal.sqlservices.MapSqlContract.Alliances;
import it.koutifaris.travianmap.dal.sqlservices.MapSqlContract.Players;
import it.koutifaris.travianmap.dal.sqlservices.MapSqlContract.Revisions;
import it.koutifaris.travianmap.dal.sqlservices.MapSqlContract.Villages;
import it.koutifaris.travianmap.dal.sqlservices.revision.SqlRevisionService;
import it.koutifaris.travianmap.mapsqlparser.MapSqlEntry;
import it.koutifaris.travianmap.mapsqlparser.MapSqlEntryHandler;

import java.util.Date;

import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;

public class TravianSqlDumpImporter implements MapSqlEntryHandler {

	private final SQLiteDatabase db;
	private Revision revision;
	private ContentValues values;
	private SQLiteStatement villageInsertStatement;

	public TravianSqlDumpImporter(SQLiteDatabase db) {
		this.db = db;
	}

	@Override
	public void init(Date lastModified) {
		SqlRevisionService sqlRevisionService = new SqlRevisionService(db);
		this.revision = sqlRevisionService.newRevisionForDay(lastModified);

		db.beginTransaction();

		initStatements();

		deleteOldData();
		saveRevision();
	}

	private void initStatements() {
		villageInsertStatement = createVillageInsertStatement();
	}

	private SQLiteStatement createVillageInsertStatement() {
		return db.compileStatement(
				"INSERT INTO " + Villages.TABLE_NAME + "("
						+ Villages.COLUMN_NAME_REVISION_ID + ","
						+ Villages.COLUMN_NAME_VILLAGE_ID + ","
						+ Villages.COLUMN_NAME_VILLAGE_NAME + ","
						+ Villages.COLUMN_NAME_POPULATION + ","
						+ Villages.COLUMN_NAME_X + ","
						+ Villages.COLUMN_NAME_Y + ","
						+ Villages.COLUMN_NAME_OWNER_ID
						+ ") VALUES(?,?,?,?,?,?,?)");
	}

	@Override
	public boolean onEntry(MapSqlEntry entry) {
		saveAlliance(entry);
		savePlayer(entry);
		saveVillage(entry);

		return true;
	}

	private void deleteOldData() {
		db.delete(Alliances.TABLE_NAME, null, null);
		db.delete(Players.TABLE_NAME, null, null);
		db.delete(Villages.TABLE_NAME, null, null);
		db.delete(Revisions.TABLE_NAME, null, null);
	}

	private void saveRevision() {
		ContentValues values = createContentValues();

		values.put(Revisions.COLUMN_NAME_DATE, revision.getDay().getTime());

		db.insertOrThrow(Revisions.TABLE_NAME, null, values);
	}

	private void saveVillage(MapSqlEntry entry) {
		bindRevision(villageInsertStatement);
		villageInsertStatement.bindLong(2, entry.getVillageId());
		villageInsertStatement.bindString(3, entry.getVillageName());
		villageInsertStatement.bindLong(4, entry.getVillagePopulation());
		villageInsertStatement.bindLong(5, entry.getX());
		villageInsertStatement.bindLong(6, entry.getY());
		villageInsertStatement.bindLong(7, entry.getPlayerId());

		villageInsertStatement.executeInsert();
	}

	private void bindRevision(SQLiteStatement statement) {
		statement.bindLong(1, revision.getId());
	}

	private void savePlayer(MapSqlEntry entry) {
		ContentValues values = createContentValues();

		values.put(Players.COLUMN_NAME_PLAYER_ID, entry.getPlayerId());
		values.put(Players.COLUMN_NAME_PLAYER_NAME, entry.getPlayerName());
		values.put(Players.COLUMN_NAME_ALLIANCE_ID, entry.getAllianceId());
		values.put(Players.COLUMN_NAME_TRIBE, entry.getTribeId());

		db.insertWithOnConflict(Players.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_IGNORE);

		// bindRevision(playerInsertStatement);
		// playerInsertStatement.bindLong(2, entry.getPlayerId());
		// playerInsertStatement.bindString(3, entry.getPlayerName());
		// playerInsertStatement.bindLong(4, entry.getAllianceId());
		// playerInsertStatement.bindLong(5, entry.getTribeId());
		//
		// try {
		// playerInsertStatement.executeInsert();
		// } catch (Exception e) {
		// }
	}

	private void saveAlliance(MapSqlEntry entry) {
		ContentValues values = createContentValues();

		values.put(Alliances.COLUMN_NAME_ALLIANCE_ID, entry.getAllianceId());
		values.put(Alliances.COLUMN_NAME_ALLIANCE_NAME, entry.getAllianceName());

		db.insertWithOnConflict(Alliances.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_IGNORE);
	}

	private ContentValues createContentValues() {
		if (values == null) {
			values = new ContentValues();
		}
		values.clear();

		values.put(Auditable.COLUMN_NAME_REVISION_ID, revision.getId());

		return values;
	}

	@Override
	public void done() {
		db.setTransactionSuccessful();
		db.endTransaction();
		// db.close();
	}

	@Override
	public void onFail(Exception e) {
		db.endTransaction();
		db.close();
	}

}
